package algorithm.encryption_decryption.aes;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AES_CBC {
    private final String CIPHERMODEPADDING = "AES/CBC/PKCS5Padding";

    private SecretKeySpec skforAES = null;
    // 密钥默认偏移，可更改
    private static final String ivParameter = "1234huangxiaoguo";

    private byte[] iv = ivParameter.getBytes();
    private IvParameterSpec IV;
    // key必须为16位，可更改为自己的key
    String sKey = "huangxiaoguo1234";

    public static void main(String[] args) {
        AES_CBC cbc = AES_CBC.getInstance();
        //加密
        String e = cbc.encrypt("asda333333333333333333333333333333333333333333333333333333sdasdasd".getBytes());
        System.out.println(e);

        //解密
        System.out.println(cbc.decrypt(e));
    }


    private static final class InstanceHolder {
        private static final AES_CBC instance = new AES_CBC();
    }

    public static AES_CBC getInstance() {
        return InstanceHolder.instance;
    }

    public AES_CBC() {
        byte[] skAsByteArray;
        skAsByteArray = sKey.getBytes(StandardCharsets.US_ASCII);
        skforAES = new SecretKeySpec(skAsByteArray, "AES");
        IV = new IvParameterSpec(iv);
    }

    public String encrypt(byte[] plaintext) {
        byte[] ciphertext = encrypt(CIPHERMODEPADDING, skforAES, IV, plaintext);
        return new String(Base64.getEncoder().encode(ciphertext));
    }

    public String decrypt(String ciphertext_base64) {
        byte[] s = Base64.getDecoder().decode(ciphertext_base64);
        return new String(decrypt(skforAES, IV, s));
    }

    private byte[] encrypt(String cmp, SecretKey sk, IvParameterSpec IV, byte[] msg) {
        try {
            Cipher c = Cipher.getInstance(cmp);
            c.init(Cipher.ENCRYPT_MODE, sk, IV);
            return c.doFinal(msg);
        } catch (Exception nsae) {
            nsae.printStackTrace();
        }
        return null;
    }

    private byte[] decrypt(SecretKey sk, IvParameterSpec IV, byte[] ciphertext) {
        try {
            Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
            c.init(Cipher.DECRYPT_MODE, sk, IV);
            return c.doFinal(ciphertext);
        } catch (Exception nsae) {
            nsae.printStackTrace();
        }
        return null;
    }
}
